import {
  Scene as ThreeScene,
  Object3D,
  PerspectiveCamera,
  AmbientLight,
  PMREMGenerator,
  WebGLRenderer,
} from 'three';

import { RGBELoader } from './Extension/RGBELoader'

export default class Scene {
  private scene: ThreeScene;
  private camera: PerspectiveCamera;
  private _currentNode: Object3D;
  private acheNode: Map<string, Object3D>;
  /**
   * get currentNode
   */
  public get currentNode() {
    return this._currentNode;
  }
  /**
   * set currentNode
   */
  public set currentNode(node: Object3D) {
    this._currentNode = node;
  }
  public get world(): ThreeScene {
    return this.scene;
  }
  public get worldCamera(): THREE.PerspectiveCamera {
    return this.camera;
  }

  public get visiableNodeIDs(): string[] {
    const ids: string[] = [];

    this.scene.traverseVisible((o) => ids.push(o.uuid));
    return ids;
  }

  constructor(width: number, height: number, renderer: WebGLRenderer) {
    this.scene = new ThreeScene();
    this.camera = new PerspectiveCamera(60, width / height, 0.1, 1000);
    this.camera.position.set(65, 89, -97);
    this.scene.add(this.camera);
    this.currentNode = this.scene;

    const pmremGenerator = new PMREMGenerator(renderer);
    pmremGenerator.compileEquirectangularShader();
    new RGBELoader().load('https://cc-sr.oss-cn-hangzhou.aliyuncs.com/static/indexModel/royal_esplanade_1k.hdr', (tex) => {

      let temp = pmremGenerator.fromEquirectangular(tex);
      this.scene.environment = temp.texture;
      //this.scene.background = temp.texture;
    })

    // new TextureLoader().load('https://cc-sr.oss-cn-hangzhou.aliyuncs.com/static/indexModel/bg.jpeg', (tex) => {

    //   let temp = pmremGenerator.fromEquirectangular(tex);
    //   this.scene.environment = temp.texture;
    //   this.scene.background = temp.texture;
    // })

    const light = new AmbientLight();
    this.addChild(light);
  }

  /**
   * acheNodes
   */
  public setAcheNodes() {
    this.acheNode = new Map();
    this.scene.traverse((obj) => this.acheNode.set(obj.uuid, obj));
  }

  /**
   * addChild
   */
  public addChild(child: Object3D) {
    this.scene.add(child);
  }

  /**
   * setNodeState
   */
  public setNodeState(id: string, state: boolean) {
    const node = this.acheNode.get(id);
    if (node) {
      node.visible = state;
      return true;
    }
  }

  /**
   * resize
   */
  public resize(width: number, height: number) {
    this.camera.aspect = width / height;
    this.camera.updateProjectionMatrix();
  }
}
